﻿using System;
using Microsoft.Popfly.GameCreator.GameEngine.Events;

namespace Microsoft.Popfly.GameCreator.GameEngine.Behaviors
{
    public class AppearBehavior : IBehavior
    {
        private double m_x;
        private double m_y;
        private Data.EffectInfo m_effect;
        private string m_explosionActorName;
        private string m_actorName;
        private Game m_game;
        private BehaviorOwner m_owner;

        public AppearBehavior(Game game, BehaviorOwner owner, Data.BehaviorInfo behaviorInfo)
        {
            m_owner = owner;
            if (behaviorInfo.GetType() != typeof(Data.AppearBehaviorInfo))
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "AppearBehavior only takes behaviorInfo of type AppearBehaviorInfo.  behaviorInfo was of type '" +
                    behaviorInfo.GetType().ToString() + "'."
                    );
            }
            Data.AppearBehaviorInfo appearInfo = (Data.AppearBehaviorInfo)behaviorInfo;

            if (appearInfo.Relative != "World")
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "AppearBehavior only handles actor appearances relative to the scene.  appearInfo.Relative was set to '" + 
                    appearInfo.Relative + 
                    "'.");
            }

            if (appearInfo.ItemReference.Includes.Count != 1)
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "There must be one actor in the includes list of an appear behavior to be able to appear an actor.  Count was '" +
                    appearInfo.ItemReference.Includes.Count +
                    "'.");
            }

            m_x = appearInfo.Left;
            m_y = appearInfo.Top;
            m_effect = appearInfo.Effect;
            if (appearInfo.ActorReference != null)
            {
                m_explosionActorName = appearInfo.ActorReference.Name;
            }
            m_game = game;

            var e = appearInfo.ItemReference.Includes.GetEnumerator();
            e.MoveNext();
            m_actorName = e.Current.Key;
        }
        public void Invoke(BehaviorOwner sender, PGCEventArgs args)
        {
            Actor actor = m_owner.Scene.AddActor(m_x, m_y, m_actorName, m_effect);

            if (m_explosionActorName != null)
            {
                m_owner.Scene.AddActor(actor, m_explosionActorName);
            }
        }
    }

    public class AppearRelativeBehavior : IBehavior
    {
        private double m_x;
        private double m_y;
        private Data.EffectInfo m_effect;
        private string m_explosionActorName;
        private string m_actorName;
        private Game m_game;
        private BehaviorOwner m_owner;

        public AppearRelativeBehavior(Game game, BehaviorOwner owner, Data.BehaviorInfo behaviorInfo)
        {
            if (behaviorInfo.GetType() != typeof(Data.AppearBehaviorInfo))
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "AppearBehavior only takes behaviorInfo of type AppearBehaviorInfo.  behaviorInfo was of type '" +
                    behaviorInfo.GetType().ToString() + "'."
                    );
            }
            Data.AppearBehaviorInfo appearInfo = (Data.AppearBehaviorInfo)behaviorInfo;

            if (appearInfo.Relative != "Parent")
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "AppearBehavior only handles actor appearances relative to the behavior owner (Parent in this case).  appearInfo.Relative was set to '" +
                    appearInfo.Relative +
                    "'.");
            }

            if (appearInfo.ItemReference.Includes.Count != 1)
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "There must be one actor in the includes list of an appear behavior to be able to appear an actor.  Count was '" +
                    appearInfo.ItemReference.Includes.Count +
                    "'.");
            }

            m_x = appearInfo.Left;
            m_y = appearInfo.Top;
            m_effect = appearInfo.Effect;
            if (appearInfo.ActorReference != null)
            {
                m_explosionActorName = appearInfo.ActorReference.Name;
            }
            m_game = game;
            m_owner = owner; 

            var e = appearInfo.ItemReference.Includes.GetEnumerator();
            e.MoveNext();
            m_actorName = e.Current.Key;
        }
        public void Invoke(BehaviorOwner sender, PGCEventArgs args)
        {
            Actor actor = m_owner.Scene.AddActor(m_owner.X + m_x, m_owner.Y + m_y, m_actorName, m_effect);

            if (m_explosionActorName != null)
            {
                m_owner.Scene.AddActor(actor, m_explosionActorName);
            }
        }
    }
}